#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

void Usage(char* args)
{
    std::cout << args << " server_port" << std::endl;
}
//const int port = 8080;

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        return -1;
    }
    // 1. 创建套接字，打开网络文件
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0)
    {
        std::cerr << "socket failed :" << errno << std::endl;
        return 1;
    }

    uint16_t port = atoi(argv[1]);

    // 2. bind IP+PORT
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        std::cerr << "bind failed :" << errno << std::endl;
        return 2;
    }

// 3. 提供服务
#define NUM 1024

    char buf[NUM] = {0};
    while (true)
    {
        struct sockaddr peer;
        socklen_t len = sizeof(peer);

        // 接受客户端信息
        ssize_t sz = recvfrom(sock, buf, NUM - 1, 0, (struct sockaddr *)&peer, &len);
        if (sz > 0)
        {
            buf[sz] = 0;
            // 执行buf的命令
            std::cout << "client# " << buf << std::endl;
            FILE *fp = popen(buf, "r");

            // 读取命令的返回信息
            std::string echo;

            char line[1024] = {0};
            while (fgets(line, NUM - 1, fp) != NULL)
            {
                echo += line;
            }

            pclose(fp);

            // 向客户端发消息
            sendto(sock, echo.c_str(), echo.size(), 0, (struct sockaddr *)&peer, len);
        }
    }
    return 0;
}

